(详细)《美国节日》:某月的第几个星期几 您所在的位置:网站首页 美国节日 今天 (详细)《美国节日》:某月的第几个星期几

(详细)《美国节日》:某月的第几个星期几

2024-07-15 19:18| 来源: 网络整理| 查看: 265

目录

一、题目描述:

 二、思路:

1、给定 年月日,如何知道这天是星期几?

2、已知这个月的第一天是星期几,如何知道第三个星期一是几号?

3、最后一个星期一

 三、思路总结

四、代码 

一、题目描述:

美国节日   美国节日

和中国的节日不同,美国的节假日通常是选择某个月的第几个星期几这种形式,因此每一年的放假日期都不相同。具体规则如下: * 1月1日:元旦 * 1月的第三个星期一:马丁·路德·金纪念日 * 2月的第三个星期一:总统节 * 5月的最后一个星期一:阵亡将士纪念日 * 7月4日:美国国庆 * 9月的第一个星期一:劳动节 * 11月的第四个星期四:感恩节 * 12月25日:圣诞节 现在给出一个年份,请你帮忙生成当年节日的日期。

输入描述:         输入包含多组数据,每组数据包含一个正整数year(2000≤year≤9999)。

输出描述:         对应每一组数据,以“YYYY-MM-DD”格式输出当年所有的节日日期,每个日期占一行。

        每组数据之后输出一个空行作为分隔。

示例1:输入: 2014 2013输出: 2014-01-01 2014-01-20 2014-02-17 2014-05-26 2014-07-04 2014-09-01 2014-11-27 2014-12-25

2013-01-01 2013-01-21 2013-02-18 2013-05-27 2013-07-04 2013-09-02 2013-11-28 2013-12-25

 二、思路:

        每年的第一天的星期几是不固定的,进而每个月的第一天是星期几也是不固定的,因此我们需要计算。

        我们要求解这个题目主要有两个大问题需要考虑:

1、给定 年月日 ,如何知道这天是星期几?2、已知这个月的第一天是星期几,如何知道第三个星期一(第一个星期一...)是几号? 1、给定 年月日,如何知道这天是星期几?

        我们需要找到一个基准值。

例如:已知今天是 2023-4-11 星期二,问2023-4-20 是星期几?

(2023-4-20) - (2023-4-11)= 9 天 ,因此 9 % 7 = 2,则2023-4-20就是 (2 + 2)% 7 = 4

         该题目中,我们以公元前1年12月31日作为基准值,已知这一天是星期7  。

(年 - 月 - 日)-(0000-12-31)= 一共多少个整年的天数 + 最后一年的天数。

例如:找 2023年 4月 11日是星期几,我们先要知道从2023-4-11到 0000-12-31 一共有多少天。

(2023-4-11)-(0000-12-31)= (0000~2023)中间年的天数 + 2023开始后面的天数(不够一年)

(1)要计算(0000~2023)中间年的天数:

0000-12-31是最后一天,因此 2023 - 0001 是中间差的年数,即(2023 - 1),说明中间有2022个年份,因此(年 - 1)。我们这里先默认这些中间的年份都是平年,因此如果有闰年的话,整体上 加上 闰年的个数 * 1(因为闰年比平年要多一天)即可。

因此公式就转化成:

(年 - 月 - 日)-(0000-12-31)= (年 - 1)* 365 + 中间闰年个数 * 1 + 最后一年的天数。

① 计算中间闰年的个数,[1,y)有多少个闰年:

        闰年:能被400整除 || 能被4整除但不能被100整除

以上面的例子来说:

(2023-4-11)-(0000-12-31) = (2023-1)*365 + 中间闰年个数*1 + 最后一年的天数

现在已知有 2022个年,要计算这2022个年中有多少年是闰年。

 要计算这2022个年中有多少个年就可以写成:

2022 / 4 - 2022 / 100 + 2022 / 400

即:可以被 4 整除的年数(y - 1)/ 4 减去 可以被100整除的年数(y - 1)/ 100 加上 可以被400整除的年数(y - 1)/ 400 。

注意:计算[ 1 , 2022 ]中有多少个数可以被 4 整除,可以直接用 2022 / 4 即可。

此时公式就转化为:(年月日用 y-m-d替换)

(y-m-d)-(0000-12-31)= (y - 1)* 365 +(y - 1)/ 4 - (y - 1)/ 100 + (y - 1) / 400 + 最后一年的天数

        因为星期一到星期天是7天一循环,而 对于 365 来说,本身就包含了很多个 7 的整数倍了,因此这里面的所有的 7 的整数倍 都可以无视掉。

365 % 7 = 1,364为 7 的整数倍,对应到星期的循环中,相当于又到星期一(最开始的时候)了。因此我们可以用 1 替换 365,最后计算的效果是一样的。

公式就变成了:  

(y-m-d)-(0000-12-31)= (y - 1) +(y - 1)/ 4 - (y - 1)/ 100 + (y - 1) / 400 + 最后一年的天数

② 最后一年的天数 :

        每个月的天数是固定的(假设是平年),因此我们可以得到一个存放每个月天数的数组。

假设要求 6 月 8日 在这年里是多少天,就要求 [1,5] 月的天数是多少,最后加上 6 。此时还要判断该年是否是闰年,如果是闰年,且要求的日期在 2 月之后(2月之前闰年和平年没区别),还要在总天数后 + 1 。

因此:

最后一年的天数 = 经过完整的月的天数之和 + d + (闰年?1:0)   (判断是否在 2 月之后)

2、已知这个月的第一天是星期几,如何知道第三个星期一是几号?

        以题中 求第三个星期一为例。

已知4月1日是星期五,求 4月的第三个星期一是几号?

 依次类推,如果4月1日是星期天、星期一、星期二......

        如果求第一个星期一:

因此我们可以总结出一个规律:

假设要找第 n 个星期 x :

(n - 1) * 7 +1 + (7 - w + x) % 7

3、最后一个星期一

        找到下个月的1日的星期数。

题目中找5月的最后一个星期一,因此我们找到该年的 6月1日是星期几,然后将6月1日看做 5月32日。

 三、思路总结

题目分析:

1、给定年月日,如何知道这一天是星期几?

(1)先要知道给定的年月日,距离基准值(0000-12-31)的天数

天数:(y-1) + (y-1)/4 - (y-1)/100 + (y-1)/400 + 最后一年的天数

最后一年的天数:经过的完整的月的天数 + d + (闰年?1:0)

(2)知道了距离基准值的天数,根据基准值(0000-12-31 星期 7),计算是星期几

星期几 = (天数 % 7) == 0 ? 7:(天数 % 7)

因为基准是 7 1 2 3 4 5 6 ,因此当 天数 % 7为 0的时候,就是第一个数字 7,而其他的来说(天数 % 7)刚好算出来的数字就对应了星期几。

2、已知1日是星期w,计算第n个星期x:

(n - 1) * 7 +1 + (7 - w + x) % 7

3、已知5月1日是星期w,计算最后一个星期一 

32 - (w == 1? 7 : w - 1) 

4、输入输出处理

        题目中输出的日期形式:2013-01-01,用printf来格式化输出时,要用 %02d 来表示后面"01"的形式。

%d :正常输出十进制数 。

%Yd:十进制数,输出 Y 位。如果本身大于 Y 位,正常输出。

%XYd:十进制数,输出 Y 位,不足 Y 位就补 X 。如果本身大于 Y 位,正常输出。

%d:十进制数正常输出 。

%2d:十进制数,输出 2 位。如果本身大于 2 位,正常输出。

%02d :十进制数,输出 2 位,不足 2 位就补 0 。如果本身大于 2 位,正常输出。

四、代码  import java.util.Scanner; /** * Created with IntelliJ IDEA. * Description:美国节日 * 1月的第三个星期一:马丁·路德·金纪念日 * 2月的第三个星期一:总统节 * 5月的最后一个星期一:阵亡将士纪念日 * 7月4日:美国国庆 * 9月的第一个星期一:劳动节 * 11月的第四个星期四:感恩节 * 12月25日:圣诞节 * User: WangWZ * Date: 2023-04-11 * Time: 15:39 */ public class Main2 { //判断是否是闰年 private static boolean isLeapYear(int y) { return ((y % 400 == 0)||(y % 4 == 0 && y % 100 != 0)); } //判断最后一年的天数 private static int lastDays(int y, int m, int d) { int[] arr = {31,28,31,30,31,30,31,31,30,31,30,31}; int ans = 0; for (int i = 0; i < m - 1; i++) { ans += arr[i]; } //最后计算不满的一个月的天数 //需要进行闰年的判断 ans += d; if(m > 2 && isLeapYear(y)) { ans += 1; } return ans; } //已知年月日,根据基准(0000-12-31 星期 7)判断有多少天 private static int nDays(int y, int m, int d){ return (y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + lastDays(y,m,d); } //1.给定 年月日 ,如何知道这天是星期几? public static int week(int y, int m, int d) { //给定年月日,要确定这天是星期几: //1.先要知道给定的年月日,距离基准值(0000-12-31)的天数 //天数:(y-1) + (y-1)/4 - (y-1)/100 + (y-1)/400 + 最后一年的天数 //最后一年的天数:经过的完整的月的天数 + d + (闰年?1:0) //2.知道了距离基准值的天数,根据基准值(0000-12-31 星期 7),计算是星期几 //星期几 = (天数 % 7) == 0 ? 7:(天数 % 7) //因为基准是 7 1 2 3 4 5 6 ,因此当 天数 % 7为 0的时候,就是第一个数字 7, //而其他的来说(天数 % 7)刚好算出来的数字就对应了星期几 int days = nDays(y,m,d); int w = days % 7; return (w == 0)?7:w; } //2.已知这个月的第一天是星期几,如何知道第三个星期一(第一个星期一...)是几号 //(1)已知 1日是星期 w,计算第 n个星期 x是几号 private static int m1(int n, int x,int w) { return (n - 1)* 7 + 1 + (7 - w + x)% 7; } //(2)根据 6月 1日是星期w,求 5月的最后一个星期一 是几号 private static int m2(int w) { return 32-((w == 1)?7:w - 1); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while(scanner.hasNextInt()) { int y = scanner.nextInt(); //1月1日:元旦 System.out.printf("%d-01-01\n", y); //1月的第三个星期一:马丁·路德·金纪念日 int w = week(y,1,1); System.out.printf("%d-01-%02d\n", y,m1(3,1,w)); //2月的第三个星期一:总统节 w = week(y,2,1); System.out.printf("%d-02-%02d\n", y,m1(3,1,w)); //5月的最后一个星期一:阵亡将士纪念日 w = week(y,6,1); System.out.printf("%d-05-%02d\n",y,m2(w)); //7月4日:美国国庆 System.out.printf("%d-07-04\n", y); //9月的第一个星期一:劳动节 w = week(y,9,1); System.out.printf("%d-09-%02d\n", y,m1(1,1,w)); //11月的第四个星期四:感恩节 w = week(y,11,1); System.out.printf("%d-11-%02d\n",y,m1(4,4,w)); //12月25日:圣诞节 System.out.printf("%d-12-25\n",y); System.out.println(); } } }



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有